/*
 * 项目名称:    wms-server-jeecg
 * 创建人员:    gongwenkai
 * 创建时间:    2023-10-16
 */
package org.jeecg.modules.flow.callback.outbound.util;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.modules.basic.material.entity.BasicMaterial;
import org.jeecg.modules.basic.material.mapper.BasicMaterialMapper;
import org.jeecg.modules.basic.material.service.IBasicMaterialService;
import org.jeecg.modules.basic.material.service.impl.BasicMaterialServiceImpl;
import org.jeecg.modules.basic.print.entity.PrintConfig;
import org.jeecg.modules.basic.print.mapper.PrintConfigMapper;
import org.jeecg.modules.basic.print.service.IPrintConfigService;
import org.jeecg.modules.basic.warehouse.entity.WmsBasicWarehouse;
import org.jeecg.modules.basic.warehouse.mapper.WmsBasicWarehouseMapper;
import org.jeecg.modules.basic.warehouse.service.IWmsBasicWarehouseAreaService;
import org.jeecg.modules.basic.warehouseGroup.entity.WmsBasicWarehouseGroupUser;
import org.jeecg.modules.basic.warehouseGroup.mapper.WmsBasicWarehouseGroupMapper;
import org.jeecg.modules.basic.warehouseGroup.mapper.WmsBasicWarehouseGroupUserMapper;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceipt;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptLoadCheck;
import org.jeecg.modules.business.doc.outbound.entity.WmsOutReceiptMaterial;
import org.jeecg.modules.business.doc.outbound.mapper.WmsOutReceiptLoadCheckMapper;
import org.jeecg.modules.business.doc.outbound.mapper.WmsOutReceiptMapper;
import org.jeecg.modules.business.doc.outbound.mapper.WmsOutReceiptMaterialMapper;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptMaterialService;
import org.jeecg.modules.business.doc.outbound.service.IWmsOutReceiptService;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTask;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskMaterial;
import org.jeecg.modules.business.outbound.entity.WmsOutReceiptTaskPick;
import org.jeecg.modules.business.outbound.entity.vo.CheckMaterialVO;
import org.jeecg.modules.business.outbound.mapper.WmsOutReceiptTaskMapper;
import org.jeecg.modules.business.outbound.mapper.WmsOutReceiptTaskMaterialMapper;
import org.jeecg.modules.business.outbound.mapper.WmsOutReceiptTaskPickMapper;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskMaterialService;
import org.jeecg.modules.business.outbound.service.IWmsOutReceiptTaskService;
import org.jeecg.modules.business.third.service.IMesStatusService;
import org.jeecg.modules.business.warehouse.entity.WmsInReceiptTask;
import org.jeecg.modules.business.warehouse.service.IWmsInReceiptTaskService;
import org.jeecg.modules.flow.callback.enums.DocumentStatusEnum;
import org.jeecg.modules.flow.callback.enums.OutboundStatusEnum;
import org.jeecg.modules.flow.sys.entity.dto.BaseFlowDto;
import org.jeecg.modules.flow.sys.exception.FlowNoActionException;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 通用出库工具类
 *
 * @author gongwenkai
 * @version 1.0.0
 * @since 2023-10-16
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class CommonOutboundUtil {

    private final WmsOutReceiptMapper wmsOutReceiptMapper;

    private final WmsOutReceiptTaskMaterialMapper wmsOutReceiptTaskMaterialMapper;

    private final WmsOutReceiptMaterialMapper wmsOutReceiptMaterialMapper;

    private final WmsOutReceiptTaskMapper wmsOutReceiptTaskMapper;

    private final IMesStatusService mesStatusService;

    private final PrintConfigMapper printConfigMapper;

    private final WmsOutReceiptTaskPickMapper wmsOutReceiptTaskPickMapper;

    private final WmsOutReceiptLoadCheckMapper wmsOutReceiptLoadCheckMapper;

    private final BasicMaterialMapper basicMaterialMapper;

    private final WmsBasicWarehouseMapper basicWarehouseMapper;

    private final WmsBasicWarehouseGroupUserMapper wmsBasicWarehouseGroupUserMapper;

    private String[] startDocumentTypes = {"C04", "C06", "C15", "C22", "C40","C43"};

    private String[] endDocumentTypes = {"C04", "C06", "C22","C15", "C40","C43","C44"};

    /**
     * 当一个表单产生通知MES任务开始
     */
    public void commonNoticeMesTaskStart(String taskId, Object data) {
        if (Objects.isNull(data)) {
            data = new Object();
        }
        WmsOutReceiptTask wmsOutReceiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if (Objects.isNull(wmsOutReceiptTask)) {
            log.error("出库任务为空");
            return;
        }
        String documentType = wmsOutReceiptTask.getDocumentType();
        if (ArrayUtil.contains(startDocumentTypes, documentType)) {
            //根据taskId判断是否是第一个表单
            long outCount = wmsOutReceiptMapper.selectCount(new LambdaQueryWrapper<WmsOutReceipt>()
                    .eq(WmsOutReceipt::getWmsOutReceiptTaskId, taskId)
            );
            if (outCount == 1) {
                // 通知MES任务开始
                try {
                    mesStatusService.outbound(taskId, null, 1, data);
                } catch (Exception e) {
                    log.error("通知失败{}", e.getMessage());
                }
            }
        }

    }

    /**
     * 当整个任务结束通知MES任务完成
     */
    public void commonNoticeMesTaskEnd(String taskId, Object data) {
        if (Objects.isNull(data)) {
            data = new Object();
        }
        WmsOutReceiptTask wmsOutReceiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if (Objects.isNull(wmsOutReceiptTask)) {
            log.error("出库任务为空");
            return;
        }
        String documentType = wmsOutReceiptTask.getDocumentType();
        if (ArrayUtil.contains(endDocumentTypes, documentType)) {
            try {
                JSONObject jsonObject = new JSONObject();
                if (documentType.equals("C06") || documentType.equals("C40")) {
                    //当纵剪叫料和纵剪叫托盘的任务需要回传鞍座信息
                    WmsOutReceipt wmsOutReceipt = wmsOutReceiptMapper.selectOne(new LambdaQueryWrapper<WmsOutReceipt>()
                            .eq(WmsOutReceipt::getWmsOutReceiptTaskId, taskId)
                            .last("LIMIT 1")
                    );
                    if (!Objects.isNull(wmsOutReceipt)) {
                        WmsOutReceiptMaterial wmsOutReceiptMaterial = wmsOutReceiptMaterialMapper.selectOne(new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                                .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, wmsOutReceipt.getId())
                                .last("LIMIT 1")
                        );
                        if (!Objects.isNull(wmsOutReceiptMaterial)) {
                            jsonObject.put("batchId", wmsOutReceiptMaterial.getBatchCode());
                            jsonObject.put("position", wmsOutReceiptMaterial.getPosition());
                        }
                    }
                    // 测试用
                    ///////////////////////////////////
//                    WmsOutReceiptTaskMaterial one = wmsOutReceiptTaskMaterialService.getOne(new LambdaQueryWrapper<WmsOutReceiptTaskMaterial>().eq(WmsOutReceiptTaskMaterial::getWmsOutReceiptTaskId, wmsOutReceiptTask.getId()));
//                    jsonObject.put("batchId", one.getBatchCode());
//                    jsonObject.put("position", "A");
//                    ////////////////////////////////////////////
//                    if(Objects.isNull(jsonObject.get("position"))||Objects.isNull(jsonObject.get("batchId"))){
//                        throw new JeecgBootException("安坐信息不存在！");
//                    }
                }
                // 通知MES任务完成
                mesStatusService.outbound(taskId, null, 2, jsonObject);
            } catch (Exception e) {
                log.error("通知失败{}", e.getMessage());
            }
        }
    }

    /**
     * 更新任务和单据物料信息
     * @param taskId
     * @param receiptId
     */
    public void updateTaskAndReceiptMaterial(String taskId,String receiptId){
        WmsOutReceipt wmsOutReceipt = wmsOutReceiptMapper.selectById(receiptId);
        if (Objects.isNull(wmsOutReceipt)) {
            return;
        }
        boolean taskOutFlag = true;
        //出库任务id
        if(StrUtil.isEmpty(taskId)){
            taskId = wmsOutReceipt.getWmsOutReceiptTaskId();
        }
        //出库任务-物料
        List<WmsOutReceiptTaskMaterial> taskMaterialList = wmsOutReceiptTaskMaterialMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptTaskMaterial>()
                .eq(WmsOutReceiptTaskMaterial::getWmsOutReceiptTaskId, taskId));
        if (CollectionUtil.isEmpty(taskMaterialList)) {
            throw new JeecgBootException("出库任务无物料明细！");
        }
        for (WmsOutReceiptTaskMaterial taskMaterial : taskMaterialList) {
            LambdaQueryWrapper<WmsOutReceiptMaterial> tempQueryWrapper = new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                    .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, wmsOutReceipt.getId());
            if (!StrUtil.isEmpty(taskMaterial.getBatchCode())) {
                tempQueryWrapper.eq(WmsOutReceiptMaterial::getBatchCode, taskMaterial.getBatchCode());
            }else{
                tempQueryWrapper.eq(WmsOutReceiptMaterial::getWmsBasicMaterialId, taskMaterial.getWmsBasicMaterialId());
            }
            List<WmsOutReceiptMaterial> receiptMaterialList = wmsOutReceiptMaterialMapper.selectList(tempQueryWrapper);
            if (!CollectionUtil.isEmpty(receiptMaterialList)) {
                //如果有这种物料，则比对任务数量和实际出库数量
                WmsOutReceiptMaterial receiptMaterial = receiptMaterialList.get(0);
                //获取未出库数量
                BigDecimal unoutboundQuantity = taskMaterial.getUnoutboundQuantity();
                if (ObjectUtil.isEmpty(unoutboundQuantity)) {
                    //如果未出库数量为空，默认为计划出库数量
                    unoutboundQuantity = taskMaterial.getPlanQuantity();
                }
                //更新数量
                if (unoutboundQuantity.compareTo(receiptMaterial.getOutboundQuantity()) > 0) {
                    //获取已出库数量
                    BigDecimal taskOutbount = ObjectUtil.isEmpty(taskMaterial.getHasOutboundQuantity()) ? BigDecimal.ZERO : taskMaterial.getHasOutboundQuantity();
                    taskMaterial.setHasOutboundQuantity(taskOutbount.add(receiptMaterial.getOutboundQuantity()));
                    taskMaterial.setUnoutboundQuantity(unoutboundQuantity.subtract(receiptMaterial.getOutboundQuantity()));
                    taskMaterial.setOutboundStatus(OutboundStatusEnum.PART.getCode());
                    wmsOutReceiptTaskMaterialMapper.updateById(taskMaterial);
                    taskOutFlag = false;
                } else if (unoutboundQuantity.compareTo(receiptMaterial.getOutboundQuantity()) == 0) {
                    taskMaterial.setHasOutboundQuantity(taskMaterial.getPlanQuantity());
                    taskMaterial.setUnoutboundQuantity(BigDecimal.ZERO);
                    taskMaterial.setOutboundStatus(OutboundStatusEnum.ALL.getCode());
                    wmsOutReceiptTaskMaterialMapper.updateById(taskMaterial);
                    taskOutFlag = true;
                } else {
                    //这种物料超计划出库
                    BigDecimal taskOutbount = ObjectUtil.isEmpty(taskMaterial.getHasOutboundQuantity()) ? BigDecimal.ZERO : taskMaterial.getHasOutboundQuantity();
                    taskMaterial.setHasOutboundQuantity(taskOutbount.add(receiptMaterial.getOutboundQuantity()));
                    taskMaterial.setUnoutboundQuantity(BigDecimal.ZERO);
                    taskMaterial.setOutboundStatus(OutboundStatusEnum.ALL.getCode());
                    wmsOutReceiptTaskMaterialMapper.updateById(taskMaterial);
                    taskOutFlag = true;
                }
                //更新辅数量
                BigDecimal unoutboundQuantityAssist = taskMaterial.getUnoutboundQuantityAssist();
                if (!Objects.isNull(unoutboundQuantityAssist) && !Objects.isNull(receiptMaterial.getOutboundQuantityAssist())) {
                    LambdaUpdateWrapper<WmsOutReceiptTaskMaterial> updateWrapper = new LambdaUpdateWrapper<WmsOutReceiptTaskMaterial>();
                    if (unoutboundQuantityAssist.compareTo(receiptMaterial.getOutboundQuantityAssist()) > 0) {
                        BigDecimal hasOutboundAssistQuantity = ObjectUtil.isEmpty(taskMaterial.getOutboundQuantityAssist()) ? BigDecimal.ZERO : taskMaterial.getOutboundQuantityAssist();
                        updateWrapper.set(WmsOutReceiptTaskMaterial::getOutboundQuantityAssist, hasOutboundAssistQuantity.add(receiptMaterial.getOutboundQuantityAssist()));
                        updateWrapper.set(WmsOutReceiptTaskMaterial::getUnoutboundQuantityAssist, unoutboundQuantityAssist.subtract(receiptMaterial.getOutboundQuantityAssist()));
                    } else if (unoutboundQuantityAssist.compareTo(receiptMaterial.getOutboundQuantityAssist()) == 0) {
                        updateWrapper.set(WmsOutReceiptTaskMaterial::getOutboundQuantityAssist, taskMaterial.getAssistQuantity());
                        updateWrapper.set(WmsOutReceiptTaskMaterial::getUnoutboundQuantityAssist, BigDecimal.ZERO);
                    } else {
                        //这种物料超计划出库
                        BigDecimal hasOutboundAssistQuantity = ObjectUtil.isEmpty(taskMaterial.getOutboundQuantityAssist()) ? BigDecimal.ZERO : taskMaterial.getOutboundQuantityAssist();
                        updateWrapper.set(WmsOutReceiptTaskMaterial::getOutboundQuantityAssist, hasOutboundAssistQuantity.add(receiptMaterial.getOutboundQuantityAssist()));
                        updateWrapper.set(WmsOutReceiptTaskMaterial::getUnoutboundQuantityAssist, BigDecimal.ZERO);
                    }
                    updateWrapper.eq(WmsOutReceiptTaskMaterial::getId, taskMaterial.getId());
                    wmsOutReceiptTaskMaterialMapper.update(null,updateWrapper);
                }
            }
        }
        //重新获取更新过的出库任务-物料
        List<WmsOutReceiptTaskMaterial> updatedList = wmsOutReceiptTaskMaterialMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptTaskMaterial>()
                .eq(WmsOutReceiptTaskMaterial::getWmsOutReceiptTaskId, taskId));
        boolean anyMatch = updatedList.stream().anyMatch(o -> o.getUnoutboundQuantity().compareTo(BigDecimal.ZERO) != 0);
        if (anyMatch) {
            taskOutFlag = false;
        }
        if (!taskOutFlag) {
            wmsOutReceiptTaskMapper.update(null,new LambdaUpdateWrapper<WmsOutReceiptTask>()
                    .set(WmsOutReceiptTask::getOutboundStatus, OutboundStatusEnum.PART.getCode())
                    .eq(WmsOutReceiptTask::getId, taskId)
            );
        } else {
            wmsOutReceiptTaskMapper.update(null,new LambdaUpdateWrapper<WmsOutReceiptTask>()
                    .set(WmsOutReceiptTask::getOutboundStatus, OutboundStatusEnum.ALL.getCode())
                    .eq(WmsOutReceiptTask::getId, taskId)
            );
        }
    }

    /**
     * 检查出库单是否数量是否超过任务数量
     */
    public void checkOrderQuantity(WmsOutReceipt wmsOutReceipt) {
        if (Objects.isNull(wmsOutReceipt)) {
            return;
        }
        //出库任务id
        String taskId = wmsOutReceipt.getWmsOutReceiptTaskId();
        //出库任务-物料
        List<WmsOutReceiptTaskMaterial> materialList = wmsOutReceiptTaskMaterialMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptTaskMaterial>()
                .eq(WmsOutReceiptTaskMaterial::getWmsOutReceiptTaskId, taskId));
        if (CollectionUtil.isEmpty(materialList)) {
            return;
        }
        for (WmsOutReceiptTaskMaterial taskMaterial : materialList) {
            LambdaQueryWrapper<WmsOutReceiptMaterial> tempQueryWrapper = new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                    .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, wmsOutReceipt.getId())
                    .eq(WmsOutReceiptMaterial::getWmsBasicMaterialId, taskMaterial.getWmsBasicMaterialId());
            if (!StrUtil.isEmpty(taskMaterial.getBatchCode())) {
                tempQueryWrapper.eq(WmsOutReceiptMaterial::getBatchCode, taskMaterial.getBatchCode());
            }else{
                tempQueryWrapper.eq(WmsOutReceiptMaterial::getWmsBasicMaterialId, taskMaterial.getWmsBasicMaterialId());
            }
            List<WmsOutReceiptMaterial> realMaterialList = wmsOutReceiptMaterialMapper.selectList(tempQueryWrapper);
            if (!CollectionUtil.isEmpty(realMaterialList)) {
                //如果有这种物料，则比对任务数量和实际出库数量
                WmsOutReceiptMaterial real = realMaterialList.get(0);
                //获取未出库数量
                BigDecimal unoutboundQuantity = taskMaterial.getUnoutboundQuantity();
                if (ObjectUtil.isEmpty(unoutboundQuantity)) {
                    //如果未出库数量为空，默认为计划出库数量
                    unoutboundQuantity = taskMaterial.getPlanQuantity();
                }
                //更新数量
                if (unoutboundQuantity.compareTo(real.getOutboundQuantity()) < 0) {

                    BasicMaterial basicMaterial = basicMaterialMapper.selectById(taskMaterial.getWmsBasicMaterialId());
                    String tempMaterialName=(Objects.isNull(basicMaterial)?taskMaterial.getMaterialCode():basicMaterial.getName())+"物料";
                    String message=tempMaterialName+"的出库量不能大于出库任务的未出库数量，当前未出库数量为"+unoutboundQuantity;
                    throw new JeecgBootException(message);
                }
            }
        }
    }
    public Boolean needPickFlag(String taskId){
        WmsOutReceiptTask receiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if(Objects.isNull(receiptTask)){
            return false;
        }
        String documentType = receiptTask.getDocumentType();
        PrintConfig printConfig = printConfigMapper.selectOne(new LambdaQueryWrapper<PrintConfig>()
                .eq(PrintConfig::getDocumentType, documentType)
                .eq(PrintConfig::getBusinessType, "outbound_task")
                .last("LIMIT 1")
        );
        if(Objects.isNull(printConfig)){
            return false;
        }
        if(Objects.isNull(printConfig.getNeedPick())){
            return false;
        }else{
            Integer needPick = printConfig.getNeedPick();
            if(needPick.equals(1)){
                return true;
            }else{
                return false;
            }
        }
    }

    public Boolean needLoadCheckFlag(String taskId){
        WmsOutReceiptTask receiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if(Objects.isNull(receiptTask)){
            return false;
        }
        String documentType = receiptTask.getDocumentType();
        PrintConfig orderPrintConfig = printConfigMapper.selectOne(new LambdaQueryWrapper<PrintConfig>()
                .eq(PrintConfig::getDocumentType, documentType)
                .eq(PrintConfig::getBusinessType, "outbound_type")
                .last("LIMIT 1")
        );
        if(Objects.isNull(orderPrintConfig)){
            return false;
        }
        if(Objects.isNull(orderPrintConfig.getNeedLoadCheck())){
            return false;
        }else{
            Integer needLoadCheck = orderPrintConfig.getNeedLoadCheck();
            if(needLoadCheck.equals(1)){
                return true;
            }else{
                return false;
            }
        }
    }

    public Boolean taskCanExecuteBatchesFlag(String taskId){
        WmsOutReceiptTask receiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if(Objects.isNull(receiptTask)){
            return false;
        }
        String documentType = receiptTask.getDocumentType();
        PrintConfig printConfig = printConfigMapper.selectOne(new LambdaQueryWrapper<PrintConfig>()
                .eq(PrintConfig::getDocumentType, documentType)
                .eq(PrintConfig::getBusinessType, "outbound_task")
                .last("LIMIT 1")
        );
        if(Objects.isNull(printConfig)){
            return false;
        }
        if(Objects.isNull(printConfig.getTaskCanExecuteBatches())){
            return false;
        }else{
            Integer canExecuteBatches = printConfig.getTaskCanExecuteBatches();
            if(canExecuteBatches.equals(1)){
                return true;
            }else{
                return false;
            }
        }
    }

    public Boolean existPickInfo(String taskId){
        boolean pickExistFlag = wmsOutReceiptTaskPickMapper.exists(new LambdaQueryWrapper<WmsOutReceiptTaskPick>()
                .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskId, taskId));
        return pickExistFlag;
    }

    public JSONObject getTaskConfig(String taskId){
        JSONObject jsonObject=new JSONObject();
        jsonObject.put("needPick",false);
        jsonObject.put("needLoadCheck",false);
        jsonObject.put("canExecuteBatchesFlag",false);
        if(StrUtil.isEmpty(taskId)){
            return jsonObject;
        }
        WmsOutReceiptTask receiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if(Objects.isNull(receiptTask)){
            return jsonObject;
        }
        String documentType = receiptTask.getDocumentType();
        PrintConfig taskPrintConfig = printConfigMapper.selectOne(new LambdaQueryWrapper<PrintConfig>()
                .eq(PrintConfig::getDocumentType, documentType)
                .eq(PrintConfig::getBusinessType, "outbound_task")
                .last("LIMIT 1")
        );
        PrintConfig orderPrintConfig = printConfigMapper.selectOne(new LambdaQueryWrapper<PrintConfig>()
                .eq(PrintConfig::getDocumentType, documentType)
                .eq(PrintConfig::getBusinessType, "outbound_type")
                .last("LIMIT 1")
        );
        if(Objects.isNull(taskPrintConfig)){
            return jsonObject;
        }
        if(Objects.isNull(taskPrintConfig.getNeedPick())){
            jsonObject.put("needPick",false);
        }else{
            Integer needPick = taskPrintConfig.getNeedPick();
            if(needPick.equals(1)){
                jsonObject.put("needPick",true);
            }else{
                jsonObject.put("needPick",false);
            }
        }
        if(Objects.isNull(orderPrintConfig)){
            jsonObject.put("needLoadCheck",false);
        }else if(Objects.isNull(orderPrintConfig.getNeedLoadCheck())){
            jsonObject.put("needLoadCheck",false);
        }else{
            Integer needLoadCheck = orderPrintConfig.getNeedLoadCheck();
            if(needLoadCheck.equals(1)){
                jsonObject.put("needLoadCheck",true);
            }else{
                jsonObject.put("needLoadCheck",false);
            }
        }
        if(Objects.isNull(taskPrintConfig.getTaskCanExecuteBatches())){
            jsonObject.put("canExecuteBatchesFlag",false);
        }else{
            Integer canExecuteBatches = taskPrintConfig.getTaskCanExecuteBatches();
            if(canExecuteBatches.equals(1)){
                jsonObject.put("canExecuteBatchesFlag",true);
            }else{
                jsonObject.put("canExecuteBatchesFlag",false);
            }
        }
        if(jsonObject.getBoolean("needPick")){
            boolean pickExistFlag = wmsOutReceiptTaskPickMapper.exists(new LambdaQueryWrapper<WmsOutReceiptTaskPick>()
                    .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskId, taskId));
            jsonObject.put("existPickInfoFlag",pickExistFlag);

            //判断是否存在已经保存或者已经提交的出库单
            boolean receiptExistFlag = wmsOutReceiptMapper.exists(new LambdaQueryWrapper<WmsOutReceipt>()
                    .eq(WmsOutReceipt::getWmsOutReceiptTaskId, taskId)
                    .ne(WmsOutReceipt::getDocumentStatus,"-1")
            );
            Boolean showPickButton=false;
            String createFrom="";
            //设置拣货按钮显隐
            if(pickExistFlag==false){
                createFrom="task";
                //不存在拣货信息
                if(receiptExistFlag==true){
                    //如果存在出库单
                    showPickButton=false;
                }else{
                    //如果不存在出库单
                    showPickButton=true;
                }
            }else{
                //存在拣货信息
                showPickButton=true;
                createFrom="pick";
            }
            jsonObject.put("showPickButton",showPickButton);
            jsonObject.put("creatOutReceiptFrom",createFrom);
        }

        return jsonObject;
    }

    /**
     * 更新任务拣货信息
     * @param receiptId
     */
    public void updateTaskPick(String receiptId) {
        WmsOutReceipt wmsOutReceipt = wmsOutReceiptMapper.selectById(receiptId);
        if (Objects.isNull(wmsOutReceipt)) {
            return;
        }
        String taskId = wmsOutReceipt.getWmsOutReceiptTaskId();
        Boolean needPickFlag = needPickFlag(taskId);
        if(!needPickFlag){
            return;
        }
        //出库单物料集合
        List<WmsOutReceiptMaterial> receiptMaterialList = wmsOutReceiptMaterialMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, receiptId)
        );
        if(CollectionUtil.isEmpty(receiptMaterialList)){
            return;
        }
        for(WmsOutReceiptMaterial receiptMaterial:receiptMaterialList){
            //查询出出库任务物料id
            String wmsOutReceiptTaskMaterialId = receiptMaterial.getWmsOutReceiptTaskMaterialId();
            //如果没有出库任务物料id
            if(StrUtil.isEmpty(wmsOutReceiptTaskMaterialId)){
                continue;
            }else{
                List<WmsOutReceiptTaskPick> pickList = wmsOutReceiptTaskPickMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptTaskPick>()
                        .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskId, taskId)
                        .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskMaterialId, wmsOutReceiptTaskMaterialId)
                );
                if(!CollectionUtil.isEmpty(pickList)){
                    pickList.stream().forEach(p->{
                        BigDecimal hasOutboundQuantity = Objects.isNull(p.getHasOutboundQuantity())?BigDecimal.ZERO:p.getHasOutboundQuantity();
                        p.setHasOutboundQuantity(hasOutboundQuantity.add(receiptMaterial.getOutboundQuantity()));
                        wmsOutReceiptTaskPickMapper.updateById(p);
                    });
                }
            }
        }
    }

    /**
     * 判断是否能分批出库提交
     */
    public void checkCanExecuteBatchCommit(String taskId,String receiptId,Boolean isSkip, BaseFlowDto baseFlowDto){
        Boolean flag = taskCanExecuteBatchesFlag(taskId);
        if(flag){
            return;
        }
        //如果不能分批出库
        List<WmsOutReceipt> list = wmsOutReceiptMapper.selectList(new LambdaQueryWrapper<WmsOutReceipt>()
                .eq(WmsOutReceipt::getWmsOutReceiptTaskId, taskId)
        );
        if(!CollectionUtil.isEmpty(list)){
            if(list.size()>1){
                throw new JeecgBootException("此任务不支持分批出库，已经存在出库单，无法出库");
            }
            if(!list.get(0).getId().equals(receiptId)){
                throw new JeecgBootException("此任务不支持分批出库，已经存在出库单，无法出库");
            }
            //对比单据物料是否全部覆盖任务物料
            String returnMessage="";
            List<WmsOutReceiptTaskMaterial> taskMaterialList = wmsOutReceiptTaskMaterialMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptTaskMaterial>()
                    .eq(WmsOutReceiptTaskMaterial::getWmsOutReceiptTaskId, taskId)
            );
            List<WmsOutReceiptMaterial> receiptMaterialList = wmsOutReceiptMaterialMapper.selectList(new LambdaUpdateWrapper<WmsOutReceiptMaterial>()
                    .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, receiptId)
            );

            for(WmsOutReceiptTaskMaterial taskMaterial:taskMaterialList){
                String taskMaterialId = taskMaterial.getId();
                Boolean passFlag=true;
                //匹配方式可能有变化
                List<WmsOutReceiptMaterial> filterList = receiptMaterialList.stream().filter(o -> taskMaterialId.equals(o.getWmsOutReceiptTaskMaterialId())).collect(Collectors.toList());
                if(CollectionUtil.isEmpty(filterList)){
                    passFlag=false;
                }else{
                    WmsOutReceiptMaterial receiptMaterial = filterList.get(0);
                    BigDecimal outboundQuantity = receiptMaterial.getOutboundQuantity();
                    BigDecimal unoutboundQuantity = taskMaterial.getUnoutboundQuantity();
                    if(unoutboundQuantity.compareTo(outboundQuantity)!=0){
                        passFlag=false;
                    }
                }
                if(passFlag==false){
                    if(StrUtil.isEmpty(returnMessage)){
                        returnMessage+=taskMaterial.getMaterialCode()+"物料编码"+taskMaterial.getBatchCode()+"批次号";
                    }else{
                        returnMessage+="、"+taskMaterial.getMaterialCode()+"物料编码"+taskMaterial.getBatchCode()+"批次号";
                    }
                }
            }
            if(!StrUtil.isEmpty(returnMessage)){
                //如果returnMessage不是空的，说明校验有问题
                //根据isSkip进行判断
                if(Objects.isNull(isSkip)){
                    //如果是空的
                    returnMessage="出库任务中的"+returnMessage+"尚未出库，提交后，任务将强制完成，不可继续执行，是否确定提交？";
                    baseFlowDto.setSecondaryBoundingBox(true);
                    Result<String> result = new Result<>();
                    result.setCode(CommonConstant.SECONDBOX);
                    result.setResult(returnMessage);
                    baseFlowDto.setResult(result);
                    //流程不执行,但是上面已保存的数据不会回滚,要么回滚,要么删除多余的数据
                    throw new FlowNoActionException("需要回滚上面已保存的数据");
                }else{
                    //如果不为空
                    if(isSkip==false){
                        returnMessage="出库任务中的"+returnMessage+"尚未出库，提交后，任务将强制完成，不可继续执行，是否确定提交？";
                        baseFlowDto.setSecondaryBoundingBox(true);
                        Result<String> result = new Result<>();
                        result.setCode(CommonConstant.SECONDBOX);
                        result.setResult(returnMessage);
                        baseFlowDto.setResult(result);
                        //流程不执行,但是上面已保存的数据不会回滚,要么回滚,要么删除多余的数据
                        throw new FlowNoActionException("需要回滚上面已保存的数据");
                    }else{
                        //前端选择跳过，更新任务状态为已完成
                        wmsOutReceiptTaskMapper.update(null,new LambdaUpdateWrapper<WmsOutReceiptTask>()
                                .set(WmsOutReceiptTask::getDocumentStatus,DocumentStatusEnum.COMPLETE.getCode())
                                .eq(WmsOutReceiptTask::getId,taskId)
                        );
                    }
                }
            }
        }
    }

    /**
     * 判断装车复核能否提交
     * @param taskId
     * @param receiptId
     */
    public void checkNeedLoadCheckCommit(String taskId,String receiptId){
        Boolean flag=needLoadCheckFlag(taskId);
        if(flag){
            //如果需要装车复核
            List<WmsOutReceiptMaterial> receiptMaterialList = wmsOutReceiptMaterialMapper.selectList(new LambdaQueryWrapper<WmsOutReceiptMaterial>()
                    .eq(WmsOutReceiptMaterial::getWmsOutReceiptId, receiptId)
            );
            Set<String> receiptMaterialIdSet = receiptMaterialList.stream().map(o -> o.getId()).collect(Collectors.toSet());
            List<WmsOutReceiptLoadCheck> loadCheckList = wmsOutReceiptLoadCheckMapper.selectList(new LambdaUpdateWrapper<WmsOutReceiptLoadCheck>()
                    .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptId, receiptId)
            );
            Set<String> loadCheckMaterialIdSet = loadCheckList.stream().map(o -> o.getWmsOutReceiptMaterialId()).collect(Collectors.toSet());
            Collection<String> subtract = CollectionUtil.subtract(receiptMaterialIdSet, loadCheckMaterialIdSet);
            if(!CollectionUtil.isEmpty(subtract)){
                   throw new JeecgBootException("物料明细和装车复核信息不一致，不可提交！");
            }
        }
    }

    /**
     * 检查需要拣货的出库单的出库数量是否正确
     */
    public void checkPickReceiptMaterialOk(String taskId,List<WmsOutReceiptMaterial> receiptMaterialList){
        if(CollectionUtil.isEmpty(receiptMaterialList)){
            log.warn("出库单物料未空,跳过");
            return;
        }
        Boolean needPickFlag = needPickFlag(taskId);
        if(!needPickFlag){
            log.warn("出库任务不需要拣货，跳过");
            return;
        }
        for(WmsOutReceiptMaterial receiptMaterial:receiptMaterialList){
            String wmsOutReceiptTaskMaterialId = receiptMaterial.getWmsOutReceiptTaskMaterialId();
            if(StrUtil.isEmpty(wmsOutReceiptTaskMaterialId)){
                continue;
            }
            WmsOutReceiptTaskPick wmsOutReceiptTaskPick = wmsOutReceiptTaskPickMapper.selectOne(new LambdaQueryWrapper<WmsOutReceiptTaskPick>()
                    .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskId, taskId)
                    .eq(WmsOutReceiptTaskPick::getWmsOutReceiptTaskMaterialId, wmsOutReceiptTaskMaterialId)
                    .last("LIMIT 1")
            );
            if(Objects.isNull(wmsOutReceiptTaskPick)){
                continue;
            }
            BigDecimal pickQuantity = Objects.isNull(wmsOutReceiptTaskPick.getPickQuantity())?BigDecimal.ZERO:wmsOutReceiptTaskPick.getPickQuantity();
            BigDecimal hasOutboundQuantity = Objects.isNull(wmsOutReceiptTaskPick.getHasOutboundQuantity())?BigDecimal.ZERO:wmsOutReceiptTaskPick.getHasOutboundQuantity();

            BigDecimal checkQuantity=pickQuantity.subtract(hasOutboundQuantity);
            BigDecimal outboundQuantity = receiptMaterial.getOutboundQuantity();
            if(checkQuantity.compareTo(outboundQuantity)<0){
                BasicMaterial basicMaterial = basicMaterialMapper.selectById(receiptMaterial.getWmsBasicMaterialId());
                String errorMessage=(Objects.isNull(basicMaterial) ? "":(basicMaterial.getName()+"物料"))
                        +(StrUtil.isEmpty(receiptMaterial.getBatchCode())?"":(receiptMaterial.getBatchCode()+"批次号"))
                        +"物料出库数量大于拣货数量";
                throw new JeecgBootException(errorMessage);
            }
        }
    }

    /**
     * 删除前校验出库单是否装车复核
     */
    public void checkOutReceiptHasLoadCheckBeforeDelete(String receiptId){
        Long existCount = wmsOutReceiptLoadCheckMapper.selectCount(new LambdaQueryWrapper<WmsOutReceiptLoadCheck>()
                .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptId, receiptId)
        );
        if(existCount>0){
            throw new JeecgBootException("存在装车复核数据，无法删除");
        }

    }

    /**
     * 更新检查前是否已经装车复核
     * @param receiptId
     */
    public void checkOutReceiptHasLoadCheckBeforeUpdate(String receiptId,List<WmsOutReceiptMaterial> receiptMaterialList){
        Boolean needLoadCheckFlag =false;
        WmsOutReceipt wmsOutReceipt = wmsOutReceiptMapper.selectById(receiptId);
        PrintConfig orderPrintConfig = printConfigMapper.selectOne(new LambdaQueryWrapper<PrintConfig>()
                .eq(PrintConfig::getDocumentType, wmsOutReceipt.getDocumentType())
                .eq(PrintConfig::getBusinessType, "outbound_type")
                .last("LIMIT 1")
        );
        if(!Objects.isNull(orderPrintConfig)){
            Integer needLoadCheck = orderPrintConfig.getNeedLoadCheck();
            Integer one=1;
            if(ObjectUtil.equal(needLoadCheck,one)){
                needLoadCheckFlag = true;
            }else{
                needLoadCheckFlag = false;
            }
        }
        if(needLoadCheckFlag){
            if(CollectionUtil.isEmpty(receiptMaterialList)){
                return;
            }
            Long existCount = wmsOutReceiptLoadCheckMapper.selectCount(new LambdaQueryWrapper<WmsOutReceiptLoadCheck>()
                    .eq(WmsOutReceiptLoadCheck::getWmsOutReceiptId, receiptId)
            );
            if(existCount>0){
                throw new JeecgBootException("存在装车复核数据，无法更新出库单物料，请到出库单列表操作");
            }
        }
    }

    /**
     * 获取出库任务是否都出完了
     * @return
     */
    public Boolean checkOutTaskComplete(String taskId){
        WmsOutReceiptTask wmsOutReceiptTask = wmsOutReceiptTaskMapper.selectById(taskId);
        if(Objects.isNull(wmsOutReceiptTask)){
            throw new JeecgBootException("出库任务不存在");
        }
        String outboundStatus = wmsOutReceiptTask.getOutboundStatus();
        if(StrUtil.isEmpty(outboundStatus)){
            return false;
        }else {
            if (outboundStatus.equals(OutboundStatusEnum.ALL.getCode())) {
                return true;
            } else {
                return false;
            }
        }
    }
}
